using System;
using System.Linq;
using System.Collections.Generic;
using Common.Unity.Extensions.PropertyMapper.Policies;
using Microsoft.Practices.ObjectBuilder2;

namespace Common.Unity.Extensions.PropertyMapper.Policies
{
	public class SimilarPropertiesPolicy : PropertyMappingPolicyBase, IMirroredPropertyMappingPolicy
	{
		readonly IEnumerable<string> excludeProperties;
		readonly bool includeNonPublicProperties;

		public SimilarPropertiesPolicy() : this( new string[0], false )
		{}

		public SimilarPropertiesPolicy( IEnumerable<string> excludeProperties ) : this( excludeProperties, false )
		{}

		public SimilarPropertiesPolicy( bool includeNonPublicProperties ) : this( new string[0], includeNonPublicProperties )
		{}

		public SimilarPropertiesPolicy( IEnumerable<string> excludeProperties, bool includeNonPublicProperties )
		{
			Guard.ArgumentNotNull( excludeProperties, "excludeProperties" );
			this.excludeProperties = excludeProperties;
			this.includeNonPublicProperties = includeNonPublicProperties;
		}

		protected override IEnumerable<IPropertySetterInfo> ResolveProperties( PropertyMappingContext context )
		{
			foreach ( string property in SimilarPropertyHelper.ResolveSimiliarProperties( context.Key, includeNonPublicProperties ) )
			{
				if ( !excludeProperties.Any( item => item == property ) )
				{
					PropertyExpressionMapping mapping = new PropertyExpressionMapping( property, property );
					IPropertySetterInfo setter = mapping.CreateProperty( context );
					yield return setter;
				}
			}
		}

		IPropertyMappingPolicy IMirroredPropertyMappingPolicy.CreateMirror()
		{
			return new SimilarPropertiesPolicy( excludeProperties, includeNonPublicProperties );
		}
	}
}